package org.openfdtd.core3d.behaviors;

import com.sun.j3d.utils.behaviors.mouse.MouseBehavior;
import java.awt.AWTEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.Enumeration;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnBehaviorPost;
import javax.vecmath.Vector3d;

/**
 *
 * @author Dorian C. Langbeck
 */
public class MouseZoom extends MouseBehavior {
	private double z_factor = .1;
	private Vector3d translation = new Vector3d();

    public MouseZoom(TransformGroup transformGroup) {
        super(transformGroup);
    }

    @Override
    public void initialize() {
	    super.initialize();
	    if ((flags & INVERT_INPUT) == INVERT_INPUT) {
            z_factor *= -1;
            invert = true;
	    }
	}

    public double getFactor() {
        return z_factor;
    }

    public void setFactor( double factor) {
        z_factor = factor;
    }


    public void processStimulus(Enumeration criteria) {
        WakeupCriterion wakeup;
        AWTEvent[] events;
        MouseEvent evt;

        while (criteria.hasMoreElements()) {
            wakeup = (WakeupCriterion) criteria.nextElement();
            if (wakeup instanceof WakeupOnAWTEvent) {
                events = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
                if (events.length > 0) {
                    evt = (MouseEvent) events[events.length-1];
                    doProcess(evt);
                }
            } else if (wakeup instanceof WakeupOnBehaviorPost) {
                while (true) {
                    synchronized (mouseq) {
                        if (mouseq.isEmpty()) break;
                        evt = (MouseEvent) mouseq.remove(0);
                        while((evt.getID() == MouseEvent.MOUSE_WHEEL) && !mouseq.isEmpty() && (((MouseEvent)mouseq.get(0)).getID() == MouseEvent.MOUSE_WHEEL))
                            evt = (MouseEvent) mouseq.remove(0);
                    }
                    doProcess(evt);
                }
            }

        }
        wakeupOn(mouseCriterion);
    }

    private void doProcess(MouseEvent evt) {
        int units = 0;

        processMouseEvent(evt);
        if ((evt.getID() == MouseEvent.MOUSE_WHEEL)) {
            MouseWheelEvent wheelEvent = (MouseWheelEvent)evt;
            if (wheelEvent.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
                units = wheelEvent.getUnitsToScroll();

            if (!reset) {
                transformGroup.getTransform(currXform);
                translation.z  = units*z_factor;
                transformX.set(translation);

                if (invert)
                    currXform.mul(currXform, transformX);
                else
                    currXform.mul(transformX, currXform);

                transformGroup.setTransform(currXform);
            } else
                reset = false;
        }
    }
}
